import { CSSProperties, FC, Fragment, useEffect, useMemo, useRef, useState } from 'react';
import { rafThrottle } from '@/utils/publicFunc';
import './index.less';
import { ICardItem, IVirtualWaterfallProps, IColumnQueue, IRenderItem, IItemRect, DataState } from './type';
import { debounce } from 'lodash';
import MyCard from './components/card';
// import { Skeleton } from 'antd';

const virtualwaterfall: FC<IVirtualWaterfallProps> = (props) => {
  const [dataState, setDataState] = useState<DataState>({
    loading: false, //发送请求的状态loading
    isFinish: false, //请求数据是否已经结束(返回空数据)
    currentPage: 0, //当前页
    list: [],
  });
  // type UpdateDataStateCallback = () => void;
  // const updateDataState = (newState: Partial<DataState>, callback?: UpdateDataStateCallback) => {
  //   dataState.current = { ...dataState.current, ...newState };
  //   if (callback) {
  //     callback();
  //   }
  // };
  const containerRef = useRef<HTMLDivElement | null>(null);
  const [scrollState, setScrollState] = useState({
    viewWidth: 0,
    viewHeight: 0,
    start: 0, //startIndex
  });
  const end = useMemo(() => scrollState.viewHeight + scrollState.start, [scrollState]); //endIndex
  const queueState = useRef({
    queue: Array(props.column)
      .fill(0)
      .map<IColumnQueue>(() => ({ list: [], height: 0 })), //存储所有卡片的二维数组
    len: 0, //存储当前视图上展示的所有卡片数量
  });
  //计算当前的最小高度列以及其索引
  const computedHeight = useRef({
    minIndex: 0,
    minHeight: Infinity,
    maxHeight: -Infinity,
  });
  const updatedHeight = () => {
    let minIndex = 0,
      minHeight = Infinity,
      maxHeight = -Infinity;
    queueState.current.queue.forEach(({ height }, index) => {
      if (height < minHeight) {
        minHeight = height;
        minIndex = index;
      }
      if (height > maxHeight) {
        maxHeight = height;
      }
    });
    computedHeight.current = { maxHeight, minHeight, minIndex };
  };
  const listStyle = useMemo(() => ({ height: `${computedHeight.current.maxHeight}px` }) as CSSProperties, [computedHeight.current.maxHeight]);
  const cardList = useRef<IRenderItem[]>([]);
  const [listTem, setListTem] = useState(cardList.current);
  const updatedCardList = () => {
    cardList.current = queueState.current.queue.reduce<IRenderItem[]>((pre, { list }) => pre.concat(list), []);
    setListTem(() => cardList.current);
  };
  //渲染元素列表
  const renderList = useMemo(() => cardList.current.filter((i: any) => i.h + i.y > scrollState.start && i.y < end), [listTem, scrollState.start, end]);
  //将原数据源item转换为cardItem并添加到dataState队列(瀑布流布局操作)
  const addInQueue = async (size: number) => {
    false && console.log('addInQueue', size);
    // size可能会超出范围，导致找不到对应的dataitem
    for (let i = 0; i < size; i++) {
      let minIndex = computedHeight.current.minIndex;
      const currentColumn = queueState.current.queue[minIndex];
      const before = currentColumn.list[currentColumn.list.length - 1] || null;
      const dataItem = dataState.list[queueState.current.len];
      false && console.log(`range-${i + 1}`);
      if (!dataItem) continue; //百万级数据可能会有性能问题
      const newItem = generatorItem(dataItem, before, minIndex);
      const updatedQueue = queueState.current.queue.map((currentQueueItem, index) => {
        if (index === minIndex) {
          return {
            list: [...currentQueueItem.list, newItem],
            height: currentQueueItem.height + newItem.h,
          };
        } else {
          return currentQueueItem;
        }
      });
      queueState.current = {
        queue: updatedQueue,
        len: queueState.current.len + 1,
      };
      updatedCardList();
      updatedHeight();
    }
  };
  //重新计算queueState中的卡片数据，瀑布流响应式
  const reComputedQueue = () => {
    //清空queueState的所有卡牌数据
    queueState.current.queue = new Array(props.column).fill(0).map<IColumnQueue>(() => ({ list: [], height: 0 }));
    queueState.current.len = 0;
  };
  //窗口发生改变
  const [resizeVar, setResizeVar] = useState(true);
  //窗口改变时执行resize
  const handleResize = debounce(() => {
    initScrollState();
    reComputedQueue();
    false && console.log('handleResize');
    setResizeVar((prevState) => !prevState);
  }, 200);
  useEffect(() => {
    window.addEventListener('resize', handleResize);
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, [resizeVar]);
  //计算卡片宽高
  const itemSizeInfo = useMemo(() => {
    const map = dataState.list.reduce<Map<ICardItem['id'], IItemRect>>((pre, current) => {
      const itemWidth = Math.floor((scrollState.viewWidth - (props.column - 1) * props.gap) / props.column);
      pre.set(current.id, {
        width: itemWidth,
        height: Math.floor((itemWidth * current.height) / current.width),
      });
      return pre;
    }, new Map());
    return map;
  }, [scrollState.viewWidth, dataState.list, props.column, props.gap, resizeVar]);
  /* isShow控制临时卡片和真实卡片的渲染，当获取到真实卡片高度信息后这个盒子就可以卸载了，挂载到真正的卡片上 ---优化失败。。。 */
  // const [isShow, setIsShow] = useState<boolean>(false);
  // const temporaryList = useRef<IBookRenderItem[]>([]);
  // const [itemSizeInfo, setItemSizeInfo] = useState(new Map<ICardItem['id'], IBookItemRect>());
  // //修改卡片属性
  // const setItemSize = () => {
  //   //async render
  //   setItemSizeInfo(() => {
  //     return dataState.list.reduce<Map<ICardItem['id'], IBookItemRect>>((pre, current) => {
  //       const itemWidth = Math.floor((scrollState.viewWidth - (props.column - 1) * props.gap) / props.column);
  //       pre.set(current.id, {
  //         width: itemWidth,
  //         height: 0,
  //         imageHeight: Math.floor((itemWidth * current.height) / current.width),
  //       });
  //       return pre;
  //     }, new Map());
  //   });
  // };
  // //mountTemporaryList：在这里挂载临时的卡片，并获取其真实高度
  // const mountTemporaryList = (list: ICardItem[]) => {
  //   setIsShow(() => false);
  //   list.forEach((item) => {
  //     const rect = itemSizeInfo.get(item.id)!;
  //     temporaryList.current.push({
  //       item,
  //       y: 0,
  //       h: 0,
  //       imageHeight: rect.imageHeight,
  //       style: {
  //         width: `${rect.width}px`,
  //       },
  //     });
  //   });
  //   (function () {
  //     const list = document.querySelector('#temporary-list')!;
  //     [...list.children].forEach((item, index) => {
  //       const rect = item.getBoundingClientRect();
  //       temporaryList.current[index].h = rect.height;
  //       setIsShow(() => true);
  //       updateItemSize();
  //       addInQueue(temporaryList.current.length);
  //       temporaryList.current = [];
  //     });
  //   })();
  // };
  // const updateItemSize = () => {
  //   temporaryList.current.forEach(({ item, h }) => {
  //     const rect = itemSizeInfo.get(item.id)!;
  //     setItemSizeInfo((prevState) => {
  //       prevState.set(item.id, { ...rect, height: h });
  //       return prevState;
  //     });
  //   });
  // };

  useEffect(() => {
    false && console.log('itemSizeInfo');
    //根据当前的数据长度全部重新添加
    addInQueue(dataState.list.length);
  }, [itemSizeInfo]);
  //生成一个item
  const generatorItem = (item: ICardItem, before: IRenderItem | null, index: number): IRenderItem => {
    const rect = itemSizeInfo.get(item.id);
    const width = rect!.width;
    const height = rect!.height;
    let y = 0;
    if (before) y = before.y + before.h + props.gap;
    return {
      item,
      y,
      h: height,
      style: {
        width: `${width}px`,
        height: `${height}px`,
        transform: `translate3d(${index === 0 ? 0 : (width + props.gap) * index}px,${y}px,0)`,
      },
    };
  };
  //初始化滚动条状态
  const initScrollState = () => {
    if (containerRef.current) {
      setScrollState(() => ({
        viewWidth: containerRef.current!.clientWidth,
        viewHeight: containerRef.current!.clientHeight,
        start: containerRef.current!.scrollTop,
      }));
    }
  };
  //初始化
  const init = async () => {
    initScrollState();
    // const list =
    await loadDataList();
    // setItemSize();
    // list && mountTemporaryList(list);
  };
  useEffect(() => {
    init();
  }, []);
  useEffect(() => {
    false && console.log('dataState.list.length', dataState.list.length);
    if (dataState.list.length > 0) {
      addInQueue(dataState.list.length);
    }
  }, [dataState.list]);
  //加载列表
  const loadDataList = async () => {
    if (dataState.isFinish) return;
    const nextPage = dataState.currentPage + 1;
    setDataState((prevState) => ({ ...prevState, currentPage: nextPage, loading: true }));
    try {
      const list = (props.request && (await props.request(nextPage, props.pageSize))) || [];
      if (!list.length) {
        setDataState((prevState) => ({
          ...prevState,
          isFinish: true,
        }));
        return;
      }
      setDataState((prevState) => ({
        ...prevState,
        list: [...prevState.list, ...list],
        loading: false,
      }));
      // return list.length;
      return list;
    } catch (error) {
      setDataState((prevState) => ({
        ...prevState,
        loading: false,
      }));
      return;
    }
  };
  //触底条件，滚动到当前最小列的高度，而不是最大列高度
  const handleScroll = rafThrottle(async () => {
    const { scrollTop, clientHeight } = containerRef.current!;
    setScrollState((prevState) => ({
      ...prevState,
      start: scrollTop,
    }));
    if (scrollTop + clientHeight > computedHeight.current.minHeight) {
      !dataState.loading && (await loadDataList());
    }
  });

  return (
    <Fragment>
      <div className="fs-virtual-waterfall-container" ref={containerRef} onScroll={handleScroll}>
        {/* 容器 */}
        <div className="fs-virtual-waterfall-list" style={listStyle}>
          {/* 列表 */}
          {renderList.map(({ item, style }) => (
            <div className="fs-virtual-waterfall-item" key={item.id} style={style}>
              {<MyCard {...item} />}
            </div>
          ))}
        </div>
      </div>
    </Fragment>
  );
};

export default virtualwaterfall;
